Imports System.Text.RegularExpressions
Imports System.Globalization

''' <summary>
''' Grilla personalisada 2.0 de MauroMix.
''' </summary>
''' <remarks></remarks>
Public Class GX_GRID
    Inherits System.Windows.Forms.DataGridView

#Region "Enumeradores"
    'Tipo de controles
    Enum Controles
        Normal
        TextBox
        CheckBox
        ComboBox
        Boton
        Imagen
    End Enum
    'Tipo de combos
    Enum Combos
        ComboA
        ComboB
        ComboC
    End Enum

    'TiposPintar filas
    Enum Estados
        SI
        NO
    End Enum

    'Tipo de datos que acepta si es textbox
    Enum TipoDeDatos
        NORMAL
        SOLO_MONEDA
        SOLO_NUMEROS
        SOLO_DECIMALES
        SOLO_TEXTO
        SOLO_DIGITO_VERIFICADOR
    End Enum

#End Region

#Region "variables"
    Private ComboBoxA As New DataGridViewComboBoxColumn
    Private ComboBoxB As New DataGridViewComboBoxColumn
    Private ComboBoxC As New DataGridViewComboBoxColumn
    Private ComboUsado As Combos
    Private IdentificarFilaColor As Boolean 'Click fila color posicion
    Private vpbVerificacion As Boolean
    Private vpiNumeroFilaAnterior As Integer
    Private TextEditCtrl As DataGridViewTextBoxEditingControl 'Crear instancia de clase de tipo textbox para grilla
    Private ColumnaTipoDeDato(100) As TipoDeDatos
#End Region

#Region "Eventos"
    Event eKeyPressCell(ByVal sender As Object, ByVal e As KeyPressEventArgs)
#End Region

#Region "Funciones Para Manipular Grilla"
    ''' <summary>
    ''' Propiedad para grilla que asigna y devulve valosres de las celdas con la propiedad value
    ''' </summary>
    ''' <param name="pci_Row"></param>
    ''' <param name="pci_Col"></param>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property TextMatrix(ByVal pci_Row As Integer, ByVal pci_Col As Integer) As Object
        Get
            Try
                Return Me.Rows(pci_Row).Cells(pci_Col).Value
            Catch ex As Exception
                MessageBox.Show(ex.ToString)
                'System.Console.WriteLine(ex.ToString)
            End Try
        End Get

        Set(ByVal value As Object)
            Try
                Me.Rows(pci_Row).DataGridView(pci_Col, pci_Row).Value = value
            Catch ex As Exception
                MessageBox.Show(ex.ToString)
            End Try
        End Set
    End Property

    ''' <summary>
    ''' Propiedad para grilla que asigna y devulve valosres de las celdas con la propiedad Tag
    ''' </summary>
    ''' <param name="pci_Row"></param>
    ''' <param name="pci_Col"></param>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property TagMatrix(ByVal pci_Row As Integer, ByVal pci_Col As Integer) As String
        Get
            Try
                Return Me.Rows(pci_Row).Cells(pci_Col).Tag
            Catch ex As Exception
                MessageBox.Show(ex.ToString)
                'System.Console.WriteLine(ex.ToString)
            End Try
        End Get

        Set(ByVal value As String)
            Try
                Me.Rows(pci_Row).DataGridView(pci_Col, pci_Row).Tag = value
            Catch ex As Exception
                'MessageBox.Show(ex.ToString)
            End Try
        End Set
    End Property

    ''' <summary>
    ''' Elimina una fila X
    ''' </summary>
    ''' <param name="pci_Row"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function RemoveItem(ByVal pci_Row As Integer)
        Try
            Me.Rows.RemoveAt(pci_Row)
        Catch ex As Exception

        End Try
    End Function

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Row() As Integer
        Get
            Try
                Return CurrentCell.RowIndex()
            Catch ex As Exception
                'MessageBox.Show(ex.ToString)
            End Try
        End Get
        Set(ByVal value As Integer)
            Try

                CurrentCell = Item(CurrentCell.ColumnIndex, value)

            Catch ex As Exception
                'MessageBox.Show(ex.ToString)
            End Try
        End Set
    End Property

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Col() As Integer
        Get
            Try
                Return CurrentCell.ColumnIndex
            Catch ex As Exception
                'MessageBox.Show(ex.ToString)
            End Try
        End Get
        Set(ByVal value As Integer)
            Try
                CurrentCell = Item(value - 1, CurrentCell.RowIndex)
            Catch ex As Exception
                'MessageBox.Show(ex.ToString)
            End Try
        End Set
    End Property

    ''' <summary>
    ''' Propiedad que devuelve y asigna filas a la grilla
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Rows_P() As Integer
        Get
            Try
                Return RowCount
            Catch ex As Exception
                'MessageBox.Show(ex.ToString)
            End Try
        End Get
        Set(ByVal value As Integer)
            Try
                RowCount = value
                Dim i As Integer
                'Codigo insertado hace poquito
                For i = 0 To Me.Rows.Count - 1
                    Me.Rows(i).Height = 20
                Next
                'fin codigo hace poquito

                ''Codigo insertado hace poquito
                'If Me.Columns.Count > 0 Then
                '    For i = 0 To Me.Columns.Count - 1
                '        Me.AlternatingRowsDefaultCellStyle.BackColor = Color.White
                '    Next i
                'End If
                ''fin codigo hace poquito
            Catch ex As Exception
                'MessageBox.Show(ex.ToString)
            End Try
        End Set
    End Property

    ''' <summary>
    ''' Propiedad que devuelve y asigna columnas en la grilla
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Cols_P() As Integer
        Get
            Try
                Return ColumnCount
            Catch ex As Exception
                'MessageBox.Show(ex.ToString)
            End Try
        End Get
        Set(ByVal value As Integer)
            Try
                ColumnCount = value
            Catch ex As Exception
                'MessageBox.Show(ex.ToString)
            End Try
        End Set
    End Property


    ''' <summary>
    ''' Propiedad para establecer o devolver el ancho de una columa
    ''' en especial
    ''' </summary>
    ''' <param name="pci_Col"></param>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property ColWidth(ByVal pci_Col As Integer) As Integer
        Get
            Try
                Return Columns(pci_Col).Width
            Catch ex As Exception

            End Try
        End Get
        Set(ByVal value As Integer)
            Try
                Columns(pci_Col).Width = value
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        End Set
    End Property

    ''' <summary>
    ''' Propiedad para establecer o devolver el alto de una fila
    ''' </summary>
    ''' <param name="pci_Row"></param>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property RotHeigth(ByVal pci_Row As Integer) As Integer
        Get
            Try
                Return Rows(pci_Row).Height
            Catch ex As Exception

            End Try
        End Get
        Set(ByVal value As Integer)
            Try
                Rows(pci_Row).Height = value
            Catch ex As Exception

            End Try
        End Set
    End Property

    ''' <summary>
    ''' Seleccionar el combo a usar en la celda 
    ''' </summary>
    ''' <param name="Combo"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function ComboActual(ByVal Combo As Combos)
        ComboUsado = Combo
    End Function



    ''' <summary>
    ''' Agregar valores en los items de algunos de los
    ''' 3 ComboBox disponibles ComboA, ComboB o ComboC
    ''' </summary>
    ''' <param name="Combo"></param>
    ''' <param name="Valor"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function AddCombo(ByVal Combo As Combos, ByVal Valor As String)
        If Combo = Combos.ComboA Then
            ComboBoxA.Items.Add(Valor)
        End If
        If Combo = Combos.ComboB Then
            ComboBoxB.Items.Add(Valor)
        End If
        If Combo = Combos.ComboC Then
            ComboBoxC.Items.Add(Valor)
        End If
    End Function


    ''' <summary>
    ''' Fija un tipo de control en la grilla:
    ''' (ComboBox,CheckBox o TextBox)
    ''' </summary>
    ''' <param name="pci_Col"></param>
    ''' <param name="Tipo"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function SetControl(ByVal pci_Col As Integer, ByVal Tipo As Controles)
        Dim CheckBox As New DataGridViewCheckBoxColumn
        Dim TextBox As New DataGridViewTextBoxColumn
        Dim Button As New DataGridViewButtonColumn
        Dim Imagen As New DataGridViewImageColumn
        Try
            If Tipo = Controles.CheckBox Then
                Columns.Insert(pci_Col, CheckBox)
            End If
            If Tipo = Controles.TextBox Then
                Columns.Insert(pci_Col, TextBox)
            End If
            If Tipo = Controles.Boton Then
                Columns.Insert(pci_Col, Button)
            End If
            If Tipo = Controles.Imagen Then
                Columns.Insert(pci_Col, Imagen)
            End If
            If Tipo = Controles.ComboBox Then
                If ComboUsado = Combos.ComboA Then
                    Columns.Insert(pci_Col, ComboBoxA)
                End If
                If ComboUsado = Combos.ComboB Then
                    Columns.Insert(pci_Col, ComboBoxB)
                End If
                If ComboUsado = Combos.ComboC Then
                    Columns.Insert(pci_Col, ComboBoxC)
                End If
            End If
        Catch ex As Exception

        End Try
    End Function


    ''' <summary>
    ''' Devuelve o Establece el estado de una columna que contenga un control
    ''' de tipo CheckBox
    ''' </summary>
    ''' <param name="pci_Col"></param>
    ''' <param name="pci_Row"></param>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property ColumnEnableCheckBox(ByVal pci_Col As Integer, ByVal pci_Row As Integer) As Boolean
        Get
            Try
                Return Item(pci_Col, pci_Row).Value
            Catch ex As Exception

            End Try
        End Get
        Set(ByVal value As Boolean)
            Try
                Item(pci_Col, pci_Row).Value = value
            Catch ex As Exception

            End Try
        End Set
    End Property


    ''' <summary>
    ''' Establece o Devuelve el texto de cabezera de una columna en particular
    ''' </summary>
    ''' <param name="pci_Col"></param>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property ColumnTextHeader(ByVal pci_Col As Integer) As String
        Get
            Try
                Return Columns(pci_Col).HeaderText.ToString
            Catch ex As Exception

            End Try
        End Get
        Set(ByVal value As String)
            Try
                Columns(pci_Col).HeaderText = value
            Catch ex As Exception

            End Try
        End Set
    End Property

    ''' <summary>
    ''' Establece o Devuelve el texto de cabezera de una columna en particular
    ''' </summary>
    ''' <param name="pci_Col"></param>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property ColumnTextHeader(ByVal pci_Col As Integer, ByVal pci_Ancho As Integer) As String
        Get
            Try
                Return Columns(pci_Col).HeaderText.ToString
            Catch ex As Exception

            End Try
        End Get
        Set(ByVal value As String)
            Try
                Columns(pci_Col).HeaderText = value
                Columns(pci_Col).Width = pci_Ancho
            Catch ex As Exception

            End Try
        End Set
    End Property

    Public Property ColVisible(ByVal pci_col As Integer) As Boolean
        Get
            Try
                Return Me.Columns(pci_col).Visible
            Catch ex As Exception

            End Try
        End Get
        Set(ByVal value As Boolean)
            Try
                Me.Columns(pci_col).Visible = value
            Catch ex As Exception

            End Try
        End Set
    End Property

    Public Function GetCellValue(ByVal pci_Row As Integer, ByVal pci_Col As Integer) As String
        Try
            Return CStr(Rows(pci_Row).Cells(pci_Col).Value)
        Catch ex As Exception

        End Try
    End Function

    'NEW
    '#################################################################
    Public Function ColumnsType(ByVal pci_Col As Integer, ByVal pce_TipoDeDatos As TipoDeDatos)
        ColumnaTipoDeDato(pci_Col) = pce_TipoDeDatos
    End Function

#Region "Texto de entrada"
    'eSTE EveNTO captura otros eventos
    'por ejemplo las celdas de la grilla se pueden dejar como cajas de textos
    'estas cajas de textos tienen eventos como keypress, change, etc...
    Private Sub GX_GRID_VIEW_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles Me.EditingControlShowing
        Try
            TextEditCtrl = CType(e.Control, DataGridViewTextBoxEditingControl)
            AddHandler TextEditCtrl.KeyPress, AddressOf TextEditCtrl_KeyPress
        Catch ex As Exception

        End Try
    End Sub

    Private Sub TextEditCtrl_KeyPress(ByVal sender As Object, _
            ByVal e As KeyPressEventArgs)

        RaiseEvent eKeyPressCell(sender, e) 'activo mi evento

        If e.KeyChar = ChrW(Keys.Enter) Then
            Try
                SendKeys.Send("{TAB}")
            Catch ex As Exception

            End Try
        End If
        If ColumnaTipoDeDato(Me.Col) = TipoDeDatos.SOLO_MONEDA Then
            e.Handled = Validar_Moneda(sender, e.KeyChar)
        End If
        If ColumnaTipoDeDato(Me.Col) = TipoDeDatos.SOLO_NUMEROS Then
            If Not fgb_ValidaCaracteres(e.KeyChar, TipoDeDatos.SOLO_NUMEROS) Then
            Else
                e.KeyChar = ChrW(0)
            End If
        End If
        If ColumnaTipoDeDato(Me.Col) = TipoDeDatos.SOLO_DECIMALES Then
            If Not fgb_ValidaCaracteres(e.KeyChar, TipoDeDatos.SOLO_DECIMALES) Then
            Else
                e.KeyChar = ChrW(0)
            End If
        End If
        If ColumnaTipoDeDato(Me.Col) = TipoDeDatos.SOLO_TEXTO Then
            If Not fgb_ValidaCaracteres(e.KeyChar, TipoDeDatos.SOLO_TEXTO) Then
            Else
                e.KeyChar = ChrW(0)
            End If
        End If
        If ColumnaTipoDeDato(Me.Col) = TipoDeDatos.SOLO_DIGITO_VERIFICADOR Then
            If Not fgb_ValidaCaracteres(e.KeyChar, TipoDeDatos.SOLO_DIGITO_VERIFICADOR) Then
            Else
                e.KeyChar = ChrW(0)
            End If
        End If
    End Sub

    ''' <summary>
    ''' Funcion que deja escribir solo caracteres permitidos 
    ''' </summary>
    ''' <param name="pcs_Caracter"></param>
    ''' <param name="pce_Control"></param>
    ''' <returns>boolean</returns>
    ''' <remarks></remarks>
    Private Function fgb_ValidaCaracteres(ByVal pcs_Caracter As Char, ByVal pce_Control As TipoDeDatos) As Boolean
        If Asc(pcs_Caracter) = 8 Or Asc(pcs_Caracter) = 13 Then
            Return False
        Else
            Select Case pce_Control
                Case TipoDeDatos.SOLO_NUMEROS
                    If Not Regex.IsMatch(pcs_Caracter, "[0-9]") Then
                        Return True
                    End If
                Case TipoDeDatos.SOLO_DECIMALES
                    If Not Regex.IsMatch(pcs_Caracter, "[0-9,]") Then
                        Return True
                    End If
                Case TipoDeDatos.SOLO_TEXTO
                    If Not Regex.IsMatch(pcs_Caracter, "[^0-9]") Then
                        Return True
                    End If
                Case TipoDeDatos.SOLO_DIGITO_VERIFICADOR
                    If Not Regex.IsMatch(pcs_Caracter, "[0-9kK]") Then
                        Return True
                    End If
            End Select
        End If
    End Function
#End Region


#End Region

#Region "Seteo de la grilla"
    'SETEO PREVIO MARCELO
    Sub MaquillaGrilla()
        Me.AllowUserToResizeRows = False
        Me.BorderStyle = Windows.Forms.BorderStyle.FixedSingle
        'Me.RowsDefaultCellStyle.SelectionBackColor = Color.White
        'Me.RowsDefaultCellStyle.SelectionForeColor = Color.Black
        'Me.BackgroundColor = Color.White
        Me.SelectionMode = DataGridViewSelectionMode.FullRowSelect
        Me.AllowUserToResizeColumns = False
        Me.AllowUserToResizeRows = False
        'Me.AlternatingRowsDefaultCellStyle.BackColor = Color.White
        For i As Integer = 0 To Me.ColumnCount - 1
            Me.Columns(i).SortMode = DataGridViewColumnSortMode.NotSortable
        Next
    End Sub
#End Region

#Region "FUNCIONES NUEVAS"
    ''' <summary>
    ''' Funcion que agrega un combobox a una columna
    ''' pero los datos son cargados de un datatable :)
    ''' </summary>
    ''' <param name="DT"></param>
    ''' <param name="Column"></param>
    ''' <param name="NameColumn"></param>
    ''' <param name="CampoPK"></param>
    ''' <param name="CampoNombre"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function AddDataTableColumn(ByVal DT As DataTable, ByVal Column As Integer, ByVal NameColumn As String, ByVal CampoPK As String, ByVal CampoNombre As String)
        Dim comboBoxColumn As New DataGridViewComboBoxColumn()
        comboBoxColumn.Name = NameColumn
        comboBoxColumn.HeaderText = NameColumn
        comboBoxColumn.Width = 160
        comboBoxColumn.DataSource = DT
        comboBoxColumn.DisplayMember = CampoNombre
        comboBoxColumn.ValueMember = CampoPK
        comboBoxColumn.Resizable = DataGridViewTriState.False
        comboBoxColumn.Frozen = True
        Me.Columns.Insert(Column, comboBoxColumn)
    End Function

    ''' <summary>
    ''' Cuando apretas una tecla, esto hace que transforme los numeros a moneda
    ''' osea le da un formato eje:  1500 -> 1.500
    ''' </summary>
    ''' <param name="cadena"></param>
    ''' <param name="key_char"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function Validar_Moneda(ByRef cadena As Object, ByVal key_char As Object) As Boolean
        Dim nfi As NumberFormatInfo = CultureInfo.CurrentCulture.NumberFormat
        Dim entero As Int64
        If IsNumeric(key_char) And cadena.Text.ToString.Length <= cadena.MaxLength Then
            cadena.AppendText(key_char)
            Dim num As String = cadena.Text.ToString().Replace(nfi.CurrencyGroupSeparator, "")
            entero = Convert.ToInt64(num)
            num = entero.ToString("N", nfi)
            num = num.Substring(0, num.Length - nfi.CurrencyDecimalDigits - 1)
            cadena.Text = ""
            cadena.AppendText(num)
        ElseIf CShort(Asc(key_char)) = 8 Then
            Dim num As String = cadena.Text.ToString().Replace(nfi.CurrencyGroupSeparator, "")
            If num <> "" Then
                num = num.Substring(0, num.Length - 1)
                If num <> "" Then
                    entero = Convert.ToInt64(num)
                    num = entero.ToString("N", nfi)
                    num = num.Substring(0, num.Length - nfi.CurrencyDecimalDigits - 1)
                End If
            End If
            cadena.Text = ""
            cadena.AppendText(num)
        End If
        Return True
    End Function
#End Region

End Class

